let Vue;
let myForEach = (obj, callback) => {
  Object.keys(obj).forEach((key) => {
    callback(key, obj[key]);
  });
};

class ModuleCollection {
  constructor(options) {
    //深度将所有的子模块都遍历一遍
    this.register([], options);
  }
  register(path, rootModule) {
    let rawModule = {
      _raw: rootModule,
      _children: {},
      state: rootModule.state,
    };
    if (!this.root) {
      this.root = rawModule;
    } else {
      let parentModule = path.slice(0, -1).reduce((root, current) => {
        return root._children[current];
      }, this.root);
      parentModule._children[path[path.length - 1]] = rawModule;
    }
    if (rootModule.modules) {
      myForEach(rootModule.modules, (moduleName, module) => {
        this.register(path.concat(moduleName), module);
      });
    }
  }
}

function installModule(store, rootState, path, rawModule) {
  if (path.length > 0) {
    let parentState = path.slice(0, -1).reduce((root, current) => {
      return rootState[current];
    }, rootState);
    Vue.set(parentState, path[path.length - 1], rawModule.state);
  }

  let getters = rawModule._raw.getters;
  if (getters) {
    myForEach(getters, (getterName, value) => {
      Object.defineProperty(store.getters, getterName, {
        get: () => {
          return value(rawModule.state);
        },
      });
    });
  }
  let mutations = rawModule._raw.mutations;
  if (mutations) {
    myForEach(mutations, (mutationName, value) => {
      console.log(
        store,
        store.mutations,
        mutationName,
        store.mutations[mutationName],
        111
      );
      let arr =
        store.mutations[mutationName] || (store.mutations[mutationName] = []);
      console.log(arr, 222);
      arr.push((payload) => {
        value(rawModule.state, payload);
      });
      console.log(arr, 333);
    });
  }
  let actions = rawModule._raw.actions;
  if (actions) {
    myForEach(actions, (actionName, value) => {
      let arr = store.actions[actionName] || (store.actions[actionName] = []);
      arr.push((payload) => {
        value(store, payload);
      });
    });
  }
  //子模块
  myForEach(rawModule._children, (moduleName, rawModule) => {
    installModule(store, rootState, path.concat(moduleName), rawModule);
  });
}

class Store {
  constructor(options) {
    //获取用户new实例中的参数
    this.vm = new Vue({
      data: {
        state: options.state,
      },
    });
    // let getters = options.getters;

    this.getters = {};
    this.mutations = {};
    this.actions = {};

    //将用户传入的数据进行格式化操作
    this.modules = new ModuleCollection(options);
    installModule(this, this.state, [], this.modules.root);
    // myForEach(getters, (getterName, value) => {
    //   Object.defineProperty(this.getters, getterName, {
    //     get: () => {
    //       return value(this.state);
    //     },
    //   });
    // });

    // let mutations = options.mutations;

    // myForEach(mutations, (mutationName, value) => {
    //   this.mutations[mutationName] = (payload) => {
    //     //订阅
    //     value(this.state, payload);
    //   };
    // });

    // let actions = options.actions;

    // myForEach(actions, (actionName, value) => {
    //   this.actions[actionName] = (payload) => {
    //     value(this, payload);
    //   };
    // });
  }
  commit = (mutationName, payload) => {
    this.mutations[mutationName].forEach((fn) => {
      fn(payload);
    }); //发布
  };

  dispatch = (actionName, payload) => {
    this.actions[actionName].forEach((fn) => {
      fn(payload);
    }); //发布;
  };

  get state() {
    return this.vm.state;
  }
}

const install = (_Vue) => {
  //vue的构造函数
  Vue = _Vue;
  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        this.$store = this.$options.store;
      } else {
        this.$store = this.$parent && this.$parent.$store;
      }
    },
  });
};

export default {
  Store,
  install,
};
